/*
 * Copyright (c) 2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.libermundi.theorcs.core.dao.hibernate;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;

/**
 * 
 * Jpa entity contribution class. For each module, declare this class to
 * contribute more managed entities.
 * 
 */
public class EntityFactoryPostProcessor implements BeanFactoryPostProcessor,
                PersistenceUnitPostProcessor {

    private static final Logger logger = LoggerFactory.getLogger(EntityFactoryPostProcessor.class);
    
    private static final String persistenceUnitPostProcessors = "persistenceUnitPostProcessors"; 

    private List<Class<?>> _managedClasses;

    public List<Class<?>> getManagedClasses() {
        return _managedClasses;
    }

    @Required
    public void setManagedClasses(List<Class<?>> managedClasses) {
        _managedClasses = managedClasses;
    }

    @Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        
        BeanDefinition entityManagerFactoryDefinition = beanFactory.getBeanDefinition("entityManagerFactory");
        PropertyValue propertyValue = entityManagerFactoryDefinition.getPropertyValues().getPropertyValue(persistenceUnitPostProcessors);
        
        if (propertyValue != null) {
            PersistenceUnitPostProcessor[] puiPostProcessor = (PersistenceUnitPostProcessor[]) entityManagerFactoryDefinition
                            .getPropertyValues().getPropertyValue(persistenceUnitPostProcessors).getValue();

            List<PersistenceUnitPostProcessor> ppList = new ArrayList<>();
            ppList.addAll(Arrays.asList(puiPostProcessor));
            ppList.add(this);
            propertyValue = new PropertyValue(persistenceUnitPostProcessors,ppList.toArray(new PersistenceUnitPostProcessor[ppList.size()]));
            entityManagerFactoryDefinition.getPropertyValues().addPropertyValue(propertyValue);
        } else {
            PersistenceUnitPostProcessor[] pp = new PersistenceUnitPostProcessor[1];
            pp[0] = this;
            propertyValue = new PropertyValue(persistenceUnitPostProcessors, pp);
            entityManagerFactoryDefinition.getPropertyValues().addPropertyValue(propertyValue);
        }
        if(logger.isDebugEnabled()){
        	logger.debug("EntityManagerFactory added PersistenceUnitPostProcessor ");
        }
    }

    @Override
	public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
        for (Class<?> clazz : _managedClasses) {
        	if(logger.isDebugEnabled()){
        		logger.debug("PersistenceUnitPostProcessor added managed class :" + clazz.getName());
        	}
            pui.addManagedClassName(clazz.getName());
        }
    }

}
